// 1-1-7 日期与时间-函数-7

/**
 * C++ 标准库没有提供所谓的日期类型。C++ 继承了 C 语言用于日期和时间操作的结构和函数。为了使用日期和时间相关的函数和结构，需要在 C++ 程序中引用 <ctime> 头文件。
 * 
 * 有四个与时间相关的类型：clock_t、time_t、size_t 和 tm。类型 clock_t、size_t 和 time_t 能够把系统时间和日期表示为某种整数。
 * 
 * 结构类型 tm 把日期和时间以 C 结构的形式保存，tm 结构的定义如下：
    struct tm {
      int tm_sec;   // 秒，正常范围从 0 到 59，但允许至 61
      int tm_min;   // 分，范围从 0 到 59
      int tm_hour;  // 小时，范围从 0 到 23
      int tm_mday;  // 一月中的第几天，范围从 1 到 31
      int tm_mon;   // 月，范围从 0 到 11
      int tm_year;  // 自 1900 年起的年数
      int tm_wday;  // 一周中的第几天，范围从 0 到 6，从星期日算起
      int tm_yday;  // 一年中的第几天，范围从 0 到 365，从 1 月 1 日算起
      int tm_isdst; // 夏令时
    };
 *
 * 下面是 C/C++ 中关于日期和时间的重要函数。所有这些函数都是 C/C++ 标准库的组成部分，您可以在 C++ 标准库中查看一下各个函数的细节。
 * 
 * 1. time_t time(time_t *time);
 * 该函数返回系统的当前日历时间，自 1970 年 1 月 1 日以来经过的秒数。如果系统没有时间，则返回 -1。
 * 
 * 2. char *ctime(const time_t *time);
 * 该返回一个表示当地时间的字符串指针，字符串形式 day month year hours:minutes:seconds year\n\0。
 * 
 * 3. struct tm *localtime(const time_t *time);
 * 该函数返回一个指向表示本地时间的 tm 结构的指针。
 * 
 * 4. clock_t clock(void);
 * 该函数返回程序执行起（一般为程序的开头），处理器时钟所使用的时间。如果时间不可用，则返回 -1。
 * 
 * 5. char * asctime ( const struct tm * time );
 * 该函数返回一个指向字符串的指针，字符串包含了 time 所指向结构中存储的信息，返回形式为：day month date hours:minutes:seconds year\n\0。
 * 
 * 6. struct tm *gmtime(const time_t *time);
 * 该函数返回一个指向 time 的指针，time 为 tm 结构，用协调世界时（UTC）也被称为格林尼治标准时间（GMT）表示。
 * 
 * 7. time_t mktime(struct tm *time);
 * 该函数返回日历时间，相当于 time 所指向结构中存储的时间。
 * 
 * 8. double difftime ( time_t time2, time_t time1 );
 * 该函数返回 time1 和 time2 之间相差的秒数。
 * 
 * 9. size_t strftime();
 * 该函数可用于格式化日期和时间为指定的格式。
*/

#include <iostream>
#include <ctime>
// #include <stdio.h>
#define BST (+1)
#define CCT (+8)

int main(void)
{

  /**
   * 7. time_t mktime(struct tm *time);
   * 描述
   * C 库函数 time_t mktime(struct tm *timeptr) 把 timeptr 所指向的结构转换为自 1970 年 1 月 1 日以来持续时间的秒数，发生错误时返回-1。
   * 
   * 参数
   * timeptr -- 这是指向表示日历时间的 time_t 值的指针，该日历时间被分解为以下各部分。下面是 timeptr 结构的细节: 
      struct tm {
        int tm_sec;   // 秒，正常范围从 0 到 59，但允许至 61
        int tm_min;   // 分，范围从 0 到 59
        int tm_hour;  // 小时，范围从 0 到 23
        int tm_mday;  // 一月中的第几天，范围从 1 到 31
        int tm_mon;   // 月，范围从 0 到 11
        int tm_year;  // 自 1900 年起的年数
        int tm_wday;  // 一周中的第几天，范围从 0 到 6，从星期日算起
        int tm_yday;  // 一年中的第几天，范围从 0 到 365，从 1 月 1 日算起
        int tm_isdst; // 夏令时
      };

  * 返回值
  * 该函数返回自 1970 年 1 月 1 日以来持续时间的秒数。如果发生错误，则返回 -1 值。
  */
  std::cout << "\n----7. time_t mktime(struct tm *time)----" << std::endl;

  time_t t;
  time(&t);
  std::cout << "time_t t :" << t << std::endl;

  // struct tm *info;
  struct tm info;

  // info = localtime(&t);
  // t = mktime(info);
  // std::cout << "mktime t :" << t << std::endl;

  struct tm *ptr; // 这个默认为未定义指针，->拿不到成员

  ptr = &info; // 必须要将该指针指向该结构对象，才能用->拿成员

  ptr->tm_year = (2021 - 1900);
  ptr->tm_mon = (9 - 1);
  ptr->tm_mday = 24;
  ptr->tm_hour = 11;
  ptr->tm_min = 11;
  ptr->tm_sec = 30;
  ptr->tm_isdst = -1;

  // info.tm_year = (2021 - 1900);
  // info.tm_mon = (9 - 1);
  // info.tm_mday = 24;
  // info.tm_hour = 11;
  // info.tm_min = 11;
  // info.tm_sec = 30;
  // info.tm_isdst = -1;

  // t = mktime(ptr);

  // t = mktime(&info);
  t = mktime(ptr);
  std::cout << "mktime t :" << t << std::endl;

  /**
   * 示例二：输入年月日判断周几
  */
  int year, month, day;
  const char *weekdays[] = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};

  // 用户输入
  printf("年:");
  fflush(stdout); // 刷新缓冲区
  scanf("%d", &year);

  printf("月:");
  fflush(stdout);
  scanf("%d", &month);

  printf("日:");
  fflush(stdout);
  scanf("%d", &day);

  struct tm date;
  struct tm *date_ptr;

  date_ptr = &date;

  // time_t tt;
  // time(&tt);
  // date_ptr = localtime(&tt);

  date_ptr->tm_year = year - 1900;
  date_ptr->tm_mon = month - 1;
  date_ptr->tm_mday = day;

  std::cout << "tm_year : " << date_ptr->tm_year << std::endl;
  std::cout << "tm_mon : " << date_ptr->tm_mon << std::endl;
  std::cout << "tm_mday : " << date_ptr->tm_mday << std::endl;
  std::cout << "tm_hour : " << date_ptr->tm_hour << std::endl;
  std::cout << "tm_min : " << date_ptr->tm_min << std::endl;
  std::cout << "tm_sec : " << date_ptr->tm_sec << std::endl;
  std::cout << "tm_wday : " << date_ptr->tm_wday << std::endl;
  std::cout << "tm_yday : " << date_ptr->tm_yday << std::endl;
  std::cout << "tm_isdst : " << date_ptr->tm_isdst << std::endl;

  
  date_ptr->tm_hour = 0;
  date_ptr->tm_min = 0;
  date_ptr->tm_sec = 0;
  date_ptr->tm_isdst = -1;

  std::cout << "---- set time ----" << std::endl;

  std::cout << "tm_year : " << date_ptr->tm_year << std::endl;
  std::cout << "tm_mon : " << date_ptr->tm_mon << std::endl;
  std::cout << "tm_mday : " << date_ptr->tm_mday << std::endl;
  std::cout << "tm_hour : " << date_ptr->tm_hour << std::endl;
  std::cout << "tm_min : " << date_ptr->tm_min << std::endl;
  std::cout << "tm_sec : " << date_ptr->tm_sec << std::endl;
  std::cout << "tm_wday : " << date_ptr->tm_wday << std::endl;
  std::cout << "tm_yday : " << date_ptr->tm_yday << std::endl;
  std::cout << "tm_isdst : " << date_ptr->tm_isdst << std::endl;

  mktime(date_ptr);

  std::cout << "---- mktime ----" << std::endl;
  std::cout << "tm_year : " << date_ptr->tm_year << std::endl;
  std::cout << "tm_mon : " << date_ptr->tm_mon << std::endl;
  std::cout << "tm_mday : " << date_ptr->tm_mday << std::endl;
  std::cout << "tm_hour : " << date_ptr->tm_hour << std::endl;
  std::cout << "tm_min : " << date_ptr->tm_min << std::endl;
  std::cout << "tm_sec : " << date_ptr->tm_sec << std::endl;
  std::cout << "tm_wday : " << date_ptr->tm_wday << std::endl;
  std::cout << "tm_yday : " << date_ptr->tm_yday << std::endl;
  std::cout << "tm_isdst : " << date_ptr->tm_isdst << std::endl;

  std::cout << year << "-" << month << "-" << day << " : " << weekdays[date_ptr->tm_wday] << std::endl;

  printf("--------------end---------------\n");
  // system("pause");
  return 0;
}